import os
import argparse
import struct
import sys

def bin2str(input_file_name, output_file_name):
    with open(input_file_name, "rb") as f:
        data_bin = f.read()
        f.close()
    data_bin_len = len(data_bin)
    func_name = sys._getframe().f_code.co_name
    print(f"{func_name}> {input_file_name} size: {data_bin_len}")

    output_file = open(output_file_name, "w")

    align = 4
    data = list(data_bin)
    if data_bin_len > 0:
        remainder = data_bin_len % align
        append_num = align - remainder
        for i in range(append_num):
            data.append(0x0)
    
    counter = 0
    while counter != len(data):
        line_string = f"{data[counter + 3]:02X}"\
                      f"{data[counter + 2]:02X}"\
                      f"{data[counter + 1]:02X}"\
                      f"{data[counter + 0]:02X}\n"
        counter += align
        output_file.writelines(line_string)

    output_file.close()


def binary_split(input_file, output_inst_name, output_data_name):
    counter = 0

    with open(input_file, "rb") as f:
        data= f.read()
        f.close()
    func_name = sys._getframe().f_code.co_name
    print(f"{func_name}> {input_file} size: {len(data)}")

    # split bin file by code and data(bss, rodata),
    # rodata relocated to data seg because 
    inst_file = open(output_inst_name, "wb")
    data_file = open(output_data_name, "wb")
    while counter != len(data):
        if counter < 0x800:
            inst_file.write(data[counter].to_bytes(1, byteorder='little'))
        else:
            data_file.write(data[counter].to_bytes(1, byteorder='little'))

        counter += 1

    inst_file.close()
    data_file.close()


def convert_bin(input_file):
    inst_bin = input_file + ".inst"
    data_bin = input_file + ".data"
    inst_str = inst_bin + ".str"
    data_str = data_bin + ".str"

    binary_split(input_file, inst_bin, data_bin)
    bin2str(inst_bin, inst_str)
    bin2str(data_bin, data_str)

def convert_dir(input_dir):
    file_names = []
    for files in os.listdir(input_dir):
        # find files ONLY with .bin rather than .bin.xxxx
        file_portion = os.path.splitext(files)
        if(file_portion[1] == '.bin'):
            file_names.append(input_dir + files)
            print(file_portion[0])
    
    for bin_file in file_names:
        convert_bin(bin_file)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', action = 'store', help = 'input binary file directory')
    args = parser.parse_args()
    input_dir = args.d
    convert_dir(input_dir)

if __name__ == '__main__':
    main()
